Skip to main content
Version: 1.0.0

updateVariantProduct

Function Name: updateVariantProduct

Author: Domenico Cerone Creation Date: 09/10/2025
Last Reviewer: Domenico Cerone

Trigger: HTTPS (onRequest)

Purpose: Complete workflow for updating existing product and variant data from catalog orders. Always downloads updated JSON and images, then updates existing documents in both Products and Variants collections. This function refreshes existing data with the latest versions from Safilo APIs without creating new documents.

Detailed Functionalityโ€‹

This Firebase Function performs a comprehensive update workflow for existing products and variants with dynamic batch processing optimized for refreshing data from catalog orders.

1. CATALOG ORDER LOADINGโ€‹

  • Receives catalogOrderId as input parameter
  • Loads document from 'CatalogOrders' collection
  • Extracts list_3d_assets_results with product array
  • Each element contains: skuCode, productRef, variantRef (existing document IDs)
  • Processes all products in list_3d_assets_results that have valid references

2. DYNAMIC BATCH PROCESSINGโ€‹

Batch configuration:

  • Fixed batch size: 10 elements with 500ms pauses between batches
  • Sequential batch processing to avoid Safilo API overload
  • Parallel processing within each batch for optimal performance
  • Individual product error handling without blocking others
  • Detailed progress logging for all operations

3. API CALLS WITH AUTOMATIC RETRY (ALWAYS EXECUTED)โ€‹

API Details:

For each product:

  • ALWAYS calls getModels API to get updated JSON data (~50KB)
  • ALWAYS downloads 8 product images (detail 00-07) with imagesize=big
  • Images are re-downloaded even if they exist (they might have changed)
  • Automatic retry system with progressive delays
  • Saves updated JSON to Firebase Storage with UUID tokens
  • Creates updated mapped JSON with public URLs

4. DOCUMENT MAPPING AND PROCESSINGโ€‹

Dynamic mapping system:

  • Dynamic parsing of mapping_template.xlsx from Firebase Storage
  • SAP metadata loading from Firebase Storage (metadata_files/)
  • Data extraction from updated JSON based on template rules
  • Automatic SAP codes translation
  • Special field handling: โ†’ SPECIAL_PRODUCT_DESCRIPTIONS: Creates separate language fields (description_en, description_it, etc.) โ†’ SPECIAL_IMAGE_NAMES: Extracts public URLs with tokens โ†’ specific posters (00,07,02,01) + list_images array
  • Updated mapped JSON save on Storage with public URL

Related Components:

  • updateProductHelper - Handles Products collection updates with thread-safe tag regeneration
  • updateVariantHelper - Handles Variants collection updates with complete field refresh
  • tagUtils - Thread-safe tag creation utilities with mutex synchronization to prevent duplicates

5. EXISTING DOCUMENT UPDATESโ€‹

Update Logic:

  • Updates existing Products document using productRef (NO creation of new documents)
  • Updates existing Variants document using variantRef (NO creation of new documents)
  • Regenerates ALL tags using thread-safe tagUtils.js functions
  • Updates ALL fields derived from mapped JSON (descriptions, images, tags, dates, etc.)
  • Maintains workflow fields unchanged (variants_map, list_variants, assignedTo, status, etc.)

Differences with populateVariantFromSkuโ€‹

Update vs Creation:

  • updateVariantProduct: ONLY updates existing documents
  • populateVariantFromSku: creation/update with complex logic

Different Input:

  • updateVariantProduct: uses productRef/variantRef from CatalogOrder
  • populateVariantFromSku: searches/creates documents by modelName/skuModel

Different Purpose:

  • updateVariantProduct: refresh existing data with updated versions
  • populateVariantFromSku: initial population from scratch

Identical Tag Handling:

  • Same tag creation/search logic using tagUtils
  • Thread-safe to avoid duplicates
  • Automatic translations (Gender โ†’ Italian)
  • Normalized brands for Line tags

Products Collection Fields Updatedโ€‹

The function updates the following fields in the Products collection with data extracted from the updated mapped JSON:

Base Fields:

  • age โ† catAgeForGender
  • manufacturedProductStatus โ† manufacturedProductStatus
  • rxAble โ† rxAble (converted from "YES"/"NO" to boolean)
  • mainBrandRef โ† ID brand (searches/creates in MainBrands collection)
  • upcCode โ† upcCode

Image Fields:

  • imgUrl โ† poster (from current variant)
  • thumbnail โ† poster (from current variant)
  • urlImage โ† poster (from current variant)

Timestamp Fields:

  • lastUpdate โ† current timestamp (always updated, Date object)
  • productReleaseDate โ† productReleaseDate (if present in mapped JSON, Date object)
  • productEndDate โ† productEndDate (if present in mapped JSON, Date object)

Multilingual Descriptions:

  • descriptionEn โ† description_en
  • descriptionIt โ† description_it
  • descriptionEs โ† description_es
  • descriptionFr โ† description_fr
  • descriptionDe โ† description_de

Tags Arrays (completely regenerated):

  • list_frame_color_tags โ† [frameColor tag IDs from Tags collection]
  • list_size_tags โ† [size tag IDs from Tags collection]
  • list_line_tags โ† [line tag IDs linked to normalized brand]
  • list_tags โ† [catType, catAgeForGender, catGender, catForma, catMaterialOne, polarised, catLensesTreat, hingeType]

Fields Maintained Unchanged:

  • modelName (primary identifier)
  • variants_map (existing variant management)
  • list_variants (existing variant IDs)
  • availableVariants (existing count)

Variants Collection Fields Updatedโ€‹

The function updates the following fields in the Variants collection with data extracted from the updated mapped JSON:

Base Fields:

  • eanCode โ† eanCode
  • frameColor โ† frameColor
  • lensesColor โ† lensesColor
  • glassesName โ† glassesName
  • mainBrandRef โ† ID brand (searches/creates in MainBrands collection)
  • upcCode โ† upcCode

Image Fields:

  • poster โ† poster (view 00 - main frontal)
  • poster2 โ† poster2 (view 07 - side angle)
  • poster3 โ† poster3 (view 02 - frontal detail)
  • poster4 โ† poster4 (view 01 - alternative angle)

Boolean Fields:

  • isADV โ† isADV (converted from "YES"/"NO" to boolean)

Size Object (all fields as strings):

  • size.bridge โ† bridge
  • size.frameWidth โ† frameWidth
  • size.lensHeight โ† lensHeight
  • size.lensWidth โ† lensWidth
  • size.size โ† size
  • size.templeLength โ† templeLength
  • size.frontHeight โ† frontHeight
  • size.hingeToHinge โ† hingeToHinge
  • size.lensCircumference โ† lensCircumference
  • size.lensAngle โ† lensAngle
  • size.phantoscopicAngle โ† phantoscopicAngle

Timestamp Fields (as JavaScript Date objects):

  • lastUpdate โ† current timestamp (always updated, Date object)
  • skuReleaseDate โ† skuReleaseDate (if present in mapped JSON, Date object)
  • skuEndDate โ† skuEndDate (if present in mapped JSON, Date object)
  • advStartDate โ† advStartDate (if present in mapped JSON, Date object)
  • advEndDate โ† advEndDate (if present in mapped JSON, Date object)

Tags Arrays (completely regenerated):

  • list_size_color_tags โ† [frameColor tag ID, size tag ID] (searches/creates in Tags collection)
  • list_images โ† list_images (array of objects with view and url of images)

Fields Maintained Unchanged:

  • skuModel (primary identifier)
  • assignedTo, assignmentDate, dataTaken
  • batch, productRef, catalogOrdersRef, prioritiesModeling
  • loadingId, mainModel, modelPriority, modelViewerUrl
  • modify_model (complete object)
  • posterNoBackground, primaryFrameColorHex, primaryLensesColorHex
  • priority, refLogVariant, secondaryFrameColorHex, secondaryLensesColorHex
  • status, templeColor
  • urlDE, urlES, urlFR, urlGlobal, urlGlobalComplete, etc.
  • variantCode, list_notes

CatalogOrder Document Structure Requiredโ€‹

Important: The function input is only the catalogOrderId. The function then loads the CatalogOrder document from Firestore and expects it to contain the following structure:

Required Fields in CatalogOrder Document:

  • clientId: ID of the client
  • list_3d_assets_results: array of products with skuCode, productRef, variantRef
  • orderName: name of the order
  • profile: client email

Product Structure in list_3d_assets_results:

{
"skuCode": "20637008650QT",
"productRef": "existing_product_document_id",
"variantRef": "existing_variant_document_id"
}

Note: The productRef and variantRef must point to existing documents in the Products and Variants collections respectively. The function will update these existing documents with fresh data from Safilo APIs.

Input (Payload)โ€‹

Method: POST

Headers:

  • Content-Type: application/json

Body:

{
"catalogOrderId": "evPBsLgU2qkGl0wCCUan"
}

Parameters:

  • catalogOrderId (string, required): Unique identifier of the catalog order to process

Output (Success)โ€‹

{
"success": true,
"catalogOrderId": "evPBsLgU2qkGl0wCCUan",
"totalProducts": 3,
"successCount": 2,
"errorCount": 1,
"processedProducts": [
{
"success": true,
"skuCode": "20637008650QT",
"productRef": "existing_product_id",
"variantRef": "existing_variant_id",
"productOperation": "update",
"variantOperation": "update",
"message": "Prodotto 20637008650QT aggiornato con successo",
"apiCalls": {
"getModels (file .json)": "https://...spaarkly.getModels?sizeCode=...",
"getImages (thumbnail images)": "https://safilo-pd-cdn002.safilo.com/..."
},
"productUpdateDetails": {
"success": true,
"operation": "update",
"documentId": "existing_product_id",
"updatedFields": ["age", "imgUrl", "list_tags", ...]
},
"variantUpdateDetails": {
"success": true,
"operation": "update",
"documentId": "existing_variant_id",
"updatedFields": ["poster", "size", "list_size_color_tags", ...]
}
}
],
"message": "Aggiornamento completato per CatalogOrder evPBsLgU2qkGl0wCCUan: 2/3 prodotti aggiornati con successo",
"requestId": "UPD_1728123456789_abc123def"
}

Technical Specificationsโ€‹

Firebase Function Configuration:

  • Timeout: 1800 seconds (30 minutes)
  • Memory: 1GiB - optimized for update operations
  • Region: europe-central2 - optimal performance for Europe
  • CORS: Enabled for frontend calls

Testingโ€‹

URL (if HTTPS): http://127.0.0.1:5001/arshadesstaging/europe-central2/updateVariantProduct

Test with Emulator:

  1. Start Firebase emulator: firebase emulators:start --only functions
  2. Ensure you're using Node.js version 20: nvm use 20
  3. Test with curl:
curl -X POST "http://127.0.0.1:5001/arshadesstaging/europe-central2/updateVariantProduct" \
-H "Content-Type: application/json" \
-d '{
"catalogOrderId": "evPBsLgU2qkGl0wCCUan"
}'

Postman Testing:

  • Method: POST
  • URL: http://127.0.0.1:5001/arshadesstaging/europe-central2/updateVariantProduct
  • Headers:
    • Key: Content-Type
    • Value: application/json
  • Body: raw JSON (see examples above)

Deploy Commandโ€‹

firebase deploy --only functions:updateVariantProduct

Production URLโ€‹

Live Function: https://europe-central2-arshades-7e18a.cloudfunctions.net/updateVariantProduct